package apps.sim.core;

import java.io.IOException;
import java.io.OutputStream;

import apps.sim.action.handler.HandlerFactory;
import apps.sim.core.log.Console;
import apps.sim.core.log.Console.Color;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

public final class HttpRequestHandler implements HttpHandler {
	public static final String HTTP_POST = "POST";
	public static final String HTTP_GET = "GET";
	private final IHandler iHandler;
	private final String context;

	public String getContext() {
		return context;
	}

	public HttpRequestHandler(String context, IHandler iHandler) {
		this.iHandler = iHandler;
		this.context = context;
	}

	public void handle(HttpExchange exchange) throws IOException {
		Console.print("Request Received at : " + exchange.getRequestURI(), Color.INFO);
		final String requestMethod = exchange.getRequestMethod();
		if (requestMethod.equalsIgnoreCase(HTTP_GET)) {
			handleGET(exchange);
		} else if (requestMethod.equalsIgnoreCase(HTTP_POST)) {
			handlePOST(exchange);
		}
	}

	private void handleGET(HttpExchange exchange) throws IOException {
		handlePOST(exchange);
	}

	private void handlePOST(HttpExchange exchange) throws IOException {
		try {
			final IHandler real = this.iHandler;
			final IHandler handler = HandlerFactory.getInstance().getHandler(real.getClass());
			if (handler instanceof AExtendedHandler) {
				((AExtendedHandler) handler).handleResponse(exchange, this.getContext());
			} else {
				final byte[] fis = handler.handle(exchange, this.getContext());
				createSuccess(exchange, fis, handler.getContentType());
			}
		} catch (Exception e) {
			createFailure(exchange, e);
		}
	}

	private void createSuccess(HttpExchange exchange, byte[] fis, String string) throws IOException {
		if (fis == null) {
			throw new IOException("Invalid response");
		}
		Headers responseHeaders = exchange.getResponseHeaders();
		responseHeaders.set("Content-Type", string);
		exchange.sendResponseHeaders(200, fis.length);
		OutputStream responseBody = exchange.getResponseBody();
		responseBody.write(fis);
		responseBody.close();
	}

	private void createFailure(HttpExchange exchange, Exception e) throws IOException {
		Headers responseHeaders = exchange.getResponseHeaders();
		responseHeaders.set("Content-Type", "text/html;charset=utf-8");
		exchange.sendResponseHeaders(500, 0);
		OutputStream responseBody = exchange.getResponseBody();
		String message = e.getMessage();
		final StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append("<html>");
		stringBuilder.append((message != null ? message : "java.lang.NullPointerException"));
		final StackTraceElement[] stackTrace = e.getStackTrace();
		for (StackTraceElement stackTraceElement : stackTrace) {
			stringBuilder.append("<br/>");
			stringBuilder.append(stackTraceElement.toString());
		}
		stringBuilder.append("</html>");
		responseBody.write(stringBuilder.toString().getBytes());
		responseBody.close();
	}
}
